package com.inspur.edp.bef.bizentity.json.object;

import com.fasterxml.jackson.core.JsonParser;
import com.inspur.edp.bef.bizentity.GspBizEntityObject;
import com.inspur.edp.bef.bizentity.LogicDeleteControlInfo;
import com.inspur.edp.bef.bizentity.beenum.BETriggerTimePointType;
import com.inspur.edp.bef.bizentity.common.BizEntityJsonConst;
import com.inspur.edp.bef.bizentity.common.InternalActionUtil;
import com.inspur.edp.bef.bizentity.common.OperationConvertUtils;
import com.inspur.edp.bef.bizentity.json.element.BizElementDeserializer;
import com.inspur.edp.bef.bizentity.json.operation.BizActionCollectionDeserializer;
import com.inspur.edp.bef.bizentity.json.operation.BizCommonDeterminationDeSerializer;
import com.inspur.edp.bef.bizentity.json.operation.BizCommonValdationDeSerializer;
import com.inspur.edp.bef.bizentity.json.operation.DtmCollectionDeserializer;
import com.inspur.edp.bef.bizentity.json.operation.TccSettingCollectionDeserializer;
import com.inspur.edp.bef.bizentity.json.operation.ValCollectionDeserializer;
import com.inspur.edp.bef.bizentity.operation.BizOperation;
import com.inspur.edp.bef.bizentity.operation.collection.BizActionCollection;
import com.inspur.edp.bef.bizentity.operation.collection.DeterminationCollection;
import com.inspur.edp.bef.bizentity.operation.collection.TccSettingCollection;
import com.inspur.edp.bef.bizentity.operation.collection.ValidationCollection;
import com.inspur.edp.bef.bizentity.operation.internalbeaction.DeleteBEAction;
import com.inspur.edp.bef.bizentity.operation.internalbeaction.ModifyBEAction;
import com.inspur.edp.bef.bizentity.operation.internalbeaction.RetrieveBEAction;
import com.inspur.edp.cef.designtime.api.collection.CommonDtmCollection;
import com.inspur.edp.cef.designtime.api.entity.GspCommonDataType;
import com.inspur.edp.cef.designtime.api.json.SerializerUtils;
import com.inspur.edp.cef.designtime.api.json.operation.CommonDtmDeserializer;
import com.inspur.edp.cef.designtime.api.json.operation.CommonValDeserializer;
import com.inspur.edp.das.commonmodel.entity.GspCommonObject;
import com.inspur.edp.das.commonmodel.entity.object.GspCommonObjectType;
import com.inspur.edp.das.commonmodel.json.element.CmElementDeserializer;
import com.inspur.edp.das.commonmodel.json.object.CmObjectDeserializer;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;

@Slf4j
public class BizObjectDeserializer extends CmObjectDeserializer {

    @Override
    protected void beforeCMObjectDeserializer(GspCommonObject commonObject) {
        GspBizEntityObject object = (GspBizEntityObject) commonObject;
        object.setDeterminations(new DeterminationCollection());
        object.setValidations(new ValidationCollection());
        object.setTccSettings(new TccSettingCollection());
        LogicDeleteControlInfo info = new LogicDeleteControlInfo();
        info.setEnableLogicDelete(false);
        object.setLogicDeleteControlInfo(info);
    }

    @Override
    protected CmObjectDeserializer createCmObjectDeserializer() {
        return new BizObjectDeserializer();
    }

    public CommonDtmDeserializer getCommonDtmDeserializer() {
        return new BizCommonDeterminationDeSerializer();
    }

    public CommonValDeserializer getCommonValDeserializer() {
        return new BizCommonValdationDeSerializer();
    }

    @Override
    protected boolean ReadExtendObjectProperty(GspCommonObject commonObject, String propName, JsonParser jsonParser) {
        boolean result = true;
        GspBizEntityObject object = (GspBizEntityObject) commonObject;
        switch (propName) {
            case BizEntityJsonConst.Determinations:
                DeterminationCollection dtms = readDeterminations(jsonParser, object);
                object.setDeterminations(dtms);
                //如果是新版编辑器保存  不拆分时机(旧元数据 用新编辑器打开保存的时候，会用到)
                if (!getFlag().equals("V2") && dtms != null && !dtms.isEmpty()) {
                    object.setDtmBeforeQuery(OperationConvertUtils
                            .convertToCommonDtms(dtms, BETriggerTimePointType.BeforeQuery));
                    object.setDtmAfterQuery(OperationConvertUtils
                            .convertToCommonDtms(dtms, BETriggerTimePointType.AfterQuery));
                    object.setDtmBeforeRetrieve(OperationConvertUtils
                            .convertToCommonDtms(dtms, BETriggerTimePointType.BeforeRetrieve));
                    object.setDtmAfterLoading(OperationConvertUtils
                            .convertToCommonDtms(dtms, BETriggerTimePointType.AfterLoading));
                    object.setDtmAfterModify(OperationConvertUtils
                            .convertToCommonDtms(dtms, BETriggerTimePointType.AfterModify));
                    object.setDtmBeforeSave(OperationConvertUtils
                            .convertToCommonDtms(dtms, BETriggerTimePointType.BeforeCheck));
                    object.setDtmAfterCreate(OperationConvertUtils
                            .convertToCommonDtms(dtms, BETriggerTimePointType.RetrieveDefault));
                    object.setDtmCancel(OperationConvertUtils
                            .convertToCommonDtms(dtms, BETriggerTimePointType.Cancel));
                }
                break;
            case BizEntityJsonConst.Validations:
                ValidationCollection vals = readValidations(jsonParser, object);
                object.setValidations(vals);
                if (vals != null && !vals.isEmpty()) {
                    object.setValAfterSave(OperationConvertUtils
                            .convertToCommonValidations(vals, BETriggerTimePointType.AfterSave));
                    object.setValAfterModify(OperationConvertUtils
                            .convertToCommonValidations(vals, BETriggerTimePointType.AfterModify));
                    object.setValBeforeSave(OperationConvertUtils
                            .convertToCommonValidations(vals, BETriggerTimePointType.BeforeCheck));
                }
                break;
            case BizEntityJsonConst.BizActions:
                readBizActions(jsonParser, object);
                break;
            case BizEntityJsonConst.AuthFieldInfos:
                readAuthFieldInfos(jsonParser, object);
                break;
            case BizEntityJsonConst.ValidationAfterSave:
                object.setValAfterSave(readCommonValidationCollection(jsonParser));
                break;
            case BizEntityJsonConst.LogicDeleteControlInfo:
                object.setLogicDeleteControlInfo(SerializerUtils.readPropertyValue_Object(LogicDeleteControlInfo.class, jsonParser));
                try {
                    jsonParser.nextToken();
                } catch (IOException e) {
                    log.error(e.getMessage());
                }
                break;
            case BizEntityJsonConst.TccSettings:
                readTccSettings(jsonParser, object);
                break;
            case BizEntityJsonConst.SecurityElementID:
                readSecurityElementID(jsonParser, object);
                break;
            case BizEntityJsonConst.ItemDeletingDtm:
                object.setItemDeletingDtms(readCommonDtmCollection(jsonParser));
                break;
            case BizEntityJsonConst.B4QueryDtm:
                object.setDtmBeforeQuery(readCommonDtmCollection(jsonParser));
                addDetermin(object, object.getDtmBeforeQuery(), BETriggerTimePointType.BeforeQuery);
                break;
            case BizEntityJsonConst.AftQueryDtm:
                object.setDtmAfterQuery(readCommonDtmCollection(jsonParser));
                addDetermin(object, object.getDtmAfterQuery(), BETriggerTimePointType.AfterQuery);
                break;
            case BizEntityJsonConst.DtmCancel:
                object.setDtmCancel(readCommonDtmCollection(jsonParser));
                addDetermin(object, object.getDtmCancel(), BETriggerTimePointType.Cancel);
                break;
            case BizEntityJsonConst.B4RetrieveDtm:
                object.setDtmBeforeRetrieve(readCommonDtmCollection(jsonParser));
                addDetermin(object, object.getDtmBeforeRetrieve(), BETriggerTimePointType.BeforeRetrieve);
                break;
            case BizEntityJsonConst.AftLoadingDtm:
                object.setDtmAfterLoading(readCommonDtmCollection(jsonParser));
                addDetermin(object, object.getDtmAfterLoading(), BETriggerTimePointType.AfterLoading);
                break;
            case BizEntityJsonConst.ItemDeletingVal:
                object.setItemDeletingVals(readCommonValidationCollection(jsonParser));
                break;
            default:
                result = false;
        }
        return result;
    }

    private void readSecurityElementID(JsonParser jsonParser, GspBizEntityObject object) {
        object.setSecurityElementID(SerializerUtils.readPropertyValue_String(jsonParser, null));
    }

    public void addDetermination(GspCommonDataType commonDataType, CommonDtmCollection dtms, String triggerType) {
        switch (triggerType) {
            case "beforeSave":
                addDetermin(commonDataType, dtms, BETriggerTimePointType.BeforeCheck);
                break;
            case "afterModify":
                addDetermin(commonDataType, dtms, BETriggerTimePointType.AfterModify);
                break;
            case "afterCreate":
                addDetermin(commonDataType, dtms, BETriggerTimePointType.RetrieveDefault);
                break;
        }
    }

    private void addDetermin(GspCommonDataType commonDataType, CommonDtmCollection commonDeterminations, BETriggerTimePointType beTriggerTimePointType) {
//        if(commonDeterminations == null || commonDeterminations.size() == 0)
//            return;
//        GspBizEntityObject bizEntityObject = (GspBizEntityObject) commonDataType;
//        DeterminationCollection dtms = OperationConvertUtils.convertToDtmCollection(commonDeterminations, beTriggerTimePointType);
//        if(bizEntityObject.getDeterminations() == null || bizEntityObject.getDeterminations().size() == 0){
//            bizEntityObject.setDeterminations(dtms);
//            return;
//        }
//        for(BizOperation determination : dtms){
//            Determination dtm = (Determination) determination;
//            BizOperation exist = bizEntityObject.getDeterminations().stream().filter(item -> item.getID().equals(dtm.getID())).findFirst().orElse(null);
//            if(exist == null){
//                bizEntityObject.getDeterminations().add(dtm);
//            }
//        }
    }

    private void readAuthFieldInfos(JsonParser jsonParser, GspBizEntityObject object) {
        SerializerUtils.readStringArray(jsonParser);
    }

    private void readBizActions(JsonParser jsonParser, GspBizEntityObject object) {
        //    BizActionCollectionDeserializer deserializer = new BizActionCollectionDeserializer();
        //    object.setBizActions(deserializer.deserialize(jsonParser, null));
        BizActionCollectionDeserializer deserializer = new BizActionCollectionDeserializer();
        BizActionCollection actionCollection = deserializer.deserialize(jsonParser, null);
        for (BizOperation action : actionCollection) {
            if (!InternalActionUtil.InternalBeActionIDs.contains(action.getID())) {
                object.getBizActions().add(action);
            }
        }
    }

    private ValidationCollection readValidations(JsonParser jsonParser, GspBizEntityObject object) {
        ValCollectionDeserializer deserializer = new ValCollectionDeserializer();
        return deserializer.deserialize(jsonParser, null);
    }

    private DeterminationCollection readDeterminations(JsonParser jsonParser, GspBizEntityObject object) {
        DtmCollectionDeserializer deserializer = new DtmCollectionDeserializer();
        return deserializer.deserialize(jsonParser, null);
    }

    private void readTccSettings(JsonParser jsonParser, GspBizEntityObject object) {
        TccSettingCollectionDeserializer deserializer = new TccSettingCollectionDeserializer();
        object.setTccSettings(deserializer.deserialize(jsonParser, null));
    }

    @Override
    protected GspCommonObject CreateCommonObject() {
        return new GspBizEntityObject();
    }

    @Override
    protected CmElementDeserializer CreateElementDeserializer() {
        return new BizElementDeserializer();
    }

    @Override
    protected void afterReadCommonDataType(GspCommonDataType commonDataType) {
        GspBizEntityObject bizObject = (GspBizEntityObject) commonDataType;
        if (bizObject.getObjectType() == GspCommonObjectType.MainObject) {
            BizActionCollection actions;
            actions = null;
            if (bizObject.getBizActions() != null && bizObject.getBizActions().size() > 0) {
                actions = bizObject.getBizActions().clone();
                bizObject.getBizActions().clear();
            }

            bizObject.getBizActions().add(new RetrieveBEAction());
            bizObject.getBizActions().add(new ModifyBEAction());
            bizObject.getBizActions().add(new DeleteBEAction());

            if (actions != null) {
                bizObject.getBizActions().addAll(actions);
            }
        }
    }
}
